package internal

import (
	"CaptchaCluster/defineMsg"
	"CaptchaCluster/log"
	"CaptchaCluster/noticeSDK"
	"github.com/name5566/leaf/gate"
	"sync"
	"sync/atomic"
	"time"
)

var conns sync.Map
var connNum int32

func init() {
	skeleton.RegisterChanRPC("NewAgent", rpcNewAgent)
	skeleton.RegisterChanRPC("CloseAgent", rpcCloseAgent)
}

func rpcNewAgent(args []interface{}) {
	a := args[0].(gate.Agent)
	_ = a

	atomic.AddInt32(&connNum, 1)
	n := atomic.LoadInt32(&connNum)
	log.Release("%s connection, number of machines:%d", a.RemoteAddr().String(), n)

	data := new(MachineData)
	data.Pong = make(chan bool)
	data.Addrr = a.RemoteAddr().String()
	data.MachineInfo = make([]defineMsg.ReqMachineInfo, 0)
	conns.Store(a, data)

	heartbeat(a)
	data.Enter()
}

func rpcCloseAgent(args []interface{}) {
	a := args[0].(gate.Agent)
	_ = a

	data, ok := conns.Load(a)
	if ok {
		atomic.AddInt32(&connNum, -1)
		n := atomic.LoadInt32(&connNum)
		log.Release("%s disconnection, number of machines:%d", a.RemoteAddr().String(), n)

		md := data.(*MachineData)
		close(md.Pong)
		conns.Delete(a)

		log.Release("%s left", md.Name)
		noticeSDK.Instance.SendMachineDown(md.Name)
		md.Quit()
	}
	a.Close()
}

func heartbeat(a gate.Agent) {
	go func() {
		defer recover()

		data, _ := conns.Load(a)

		t := time.NewTimer(5 * time.Second)
		select {
		case <-data.(*MachineData).Pong:
		case <-t.C:
			log.Release("%s heartbeat timeout", a.RemoteAddr().String())
			a.Close()
		}
		t.Stop()
	}()
}
